home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / comm2 / kms20src.lha / KMSC / inout.c < prev    next >
C/C++ Source or Header  |  1995-05-05  |  40KB  |  1,527 lines

  1. /**********************************
  2.  *              KMS               *
  3.  **********************************
  4.  *  ©1993 by BlackMagic Software  *
  5.  **********************************
  6.  *                                *
  7.  **********************************/
  8.  
  9. #include <KMS/KMS.h>
  10. #include <KMS/KMS_devlib.h>
  11. #include <KMS/KMS_intui.h>
  12.  
  13. Prototype VOID FlushInput(VOID);
  14. Prototype VOID SetTimer(ULONG, ULONG);
  15. Prototype UBYTE Print(STRPTR, UWORD);
  16. Prototype UBYTE BreakCheck(UWORD);
  17. Prototype VOID XOff(VOID);
  18. Prototype VOID OutChar(TEXT);
  19. Prototype VOID OutBuffer(BPTR, TEXT);
  20. Prototype VOID OutString(BPTR, STRPTR);
  21. Prototype LONG CmdInput(STRPTR, UWORD, STRPTR, STRPTR, UWORD, UWORD);
  22. Prototype BOOL PlopCheck(UBYTE, UWORD);
  23. Prototype WORD InKey(WORD);
  24. Prototype WORD InKeyNew(WORD);
  25. Prototype TEXT ReadKey(VOID);
  26. Prototype UWORD CheckCSI(TEXT);
  27. Prototype BOOL StringSearch(STRPTR, STRPTR);
  28. Prototype VOID DoFKey(UWORD);
  29. Prototype ULONG MakeTime(STRPTR, time_t, time_t);
  30. Prototype VOID CursorOn(VOID);
  31. Prototype VOID CursorOff(VOID);
  32. Prototype VOID DelInputChar(UWORD);
  33. Prototype VOID InsInputChar(UWORD);
  34. Prototype VOID ChatOut(STRPTR, UWORD);
  35. Prototype VOID Error(STRPTR);
  36.  
  37. extern VOID KPrintF(APTR, ...);
  38.  
  39. /*****************************
  40.  * Externe Globale Variablen *
  41.  *****************************/
  42.  
  43. extern struct timerequest *Time_Request;
  44. extern struct MsgPort *Timer_Port;
  45. extern struct DosPacket *InputPacket;
  46.  
  47. extern struct KMSBase *KMSBase;
  48. extern struct LocalConfig *KMS_LC;
  49.  
  50. extern ULONG TimerSignal, RexxSignal, InputSignal;
  51.  
  52. extern UWORD AutoAct;
  53.  
  54. extern UBYTE LazyCount;
  55.  
  56. extern STRPTR PPArg;
  57.  
  58. extern UBYTE ShutDown;
  59.  
  60. extern BPTR StdErr;
  61.  
  62. /*********************
  63.  * Globale Variablen *
  64.  *********************/
  65.  
  66. UBYTE Plop = 0;
  67.  
  68. BOOL Spying = FALSE;
  69.  
  70. /****************************
  71.  * Lese-Kanal leeren        *
  72.  ****************************
  73.  * I: ---                   *
  74.  * O: ---                   *
  75.  ****************************/
  76.  
  77. /// "FlushInput"
  78.  
  79. VOID FlushInput(VOID)
  80.    {
  81.    TEXT buff[128];
  82.    WORD len;
  83.  
  84.    while(WaitForChar(KMS_LC->InHandle, 0) == DOSTRUE)
  85.       {
  86.       len = Read(KMS_LC->InHandle, buff, sizeof(buff));
  87.       SetSignal(0, SIGBREAKF_CTRL_C);
  88.  
  89.       if (len <= 0)
  90.          {
  91.          /* EOF/Fehler: Plop und raus */
  92.  
  93.          Plop = PLOP_BREAKC;
  94.          
  95.          return;
  96.          }
  97.       }
  98.    }
  99.  
  100. ///
  101.  
  102. /************************************
  103.  * Timer initialisieren und starten *
  104.  ************************************
  105.  * I: Sekunden und Mikrosekunden    *
  106.  * O: ---                           *
  107.  ************************************/
  108.  
  109. /// "SetTimer"
  110.  
  111. VOID SetTimer(ULONG secs, ULONG micros)
  112.    {
  113.    Time_Request->tr_node.io_Command = TR_ADDREQUEST;
  114.    Time_Request->tr_node.io_Flags   = 0;
  115.    Time_Request->tr_time.tv_secs    = secs;
  116.    Time_Request->tr_time.tv_micro   = micros;
  117.    SendIO((struct IORequest *)Time_Request);
  118.    }
  119.  
  120. ///
  121.  
  122. /***************************************
  123.  * Standard Textausgabe (Zeichenkette) *
  124.  ***************************************
  125.  * I: String, Flags                    *
  126.  * O: CTRL-X, CTRL-C oder 0            *
  127.  ***************************************/
  128.  
  129. /// "Print"
  130.  
  131. UBYTE Print(STRPTR string, UWORD flags)
  132.    {
  133.    UWORD i = 0;
  134.    UBYTE c;
  135.  
  136.    if (string)
  137.       {
  138.       while(string[i])
  139.          OutChar(string[i++]);
  140.  
  141.       if (!(flags & PF_NOBRK) && (c = BreakCheck(flags)))
  142.          {
  143.          OutChar('\r');
  144.          OutChar('\n');
  145.  
  146.          return c;
  147.          }
  148.       }
  149.  
  150.    if (!(flags & PF_NOLF))
  151.       {
  152.       OutChar('\r');
  153.       OutChar('\n');
  154.       }
  155.    else
  156.       OutChar(0);
  157.  
  158.    return 0;
  159.    }
  160.  
  161. ///
  162.  
  163. /*****************************************
  164.  * Auf CTRL-X CTRL-C CTRL-S prüfen       *
  165.  *****************************************
  166.  * I: Flags PF_CTRLC|PF_CTRLX|PF_NOCTRLS *
  167.  * O: ^X, ^C oder 0                      *
  168.  *****************************************/
  169.  
  170. /// "BreakCheck"
  171.  
  172. UBYTE BreakCheck(UWORD flags)
  173.    {
  174.    TEXT c = 0;
  175.  
  176.    if (c = ReadKey())
  177.       {
  178.       switch(c)
  179.          {
  180.          case 3:
  181.             if (!(flags & PF_CTRLC))
  182.                c = 0;
  183.             break;
  184.          case 19:
  185.             if (!(flags & PF_NOCTRLS))
  186.                XOff();
  187.             c = 0;
  188.             break;
  189.          case 24:
  190.             if (!(flags & PF_CTRLX))
  191.                c = 0;
  192.             break;
  193.          default:
  194.             c = 0;
  195.          }
  196.       }
  197.  
  198.    return c;
  199.    }
  200.  
  201. ///
  202.  
  203. /***************************************
  204.  * CTRLS-Pause                         *
  205.  ***************************************
  206.  * I: ---                              *
  207.  * O: ---                              *
  208.  ***************************************/
  209.  
  210. /// "XOff"
  211.  
  212. VOID XOff(VOID)
  213.    {
  214.    OutChar(0);
  215.    InKey(KMSBase->XOFFTimeout);
  216.    }
  217.  
  218. ///
  219.  
  220. /*************************************
  221.  * Senden eines Zeichens             *
  222.  *************************************
  223.  * I: Zeichen                        *
  224.  * O: ---                            *
  225.  *************************************/
  226.  
  227. /// "OutChar"
  228.  
  229. VOID OutChar(TEXT c)
  230.    {
  231.    OutBuffer(KMS_LC->OutHandle, KMSBase->CharOut[KMS_LC->Session.CurrentUser->UserData.CharSet][c]);
  232.    }
  233.  
  234. ///
  235.  
  236. /****************************************
  237.  * Ausgabe-Pufferung                    *
  238.  ****************************************
  239.  * I: Zeichen                           *
  240.  * O: ---                               *
  241.  ****************************************/
  242.  
  243. /// "OutBuffer"
  244.  
  245. TEXT OutputBuffer[LEN_OUTPUT+1];
  246.  
  247. VOID OutBuffer(BPTR handle, TEXT c)
  248.    {
  249.    static UWORD pos = 0;
  250.  
  251.    OutputBuffer[pos++] = c;
  252.  
  253.    if (c == '\0' || c == '\n' || pos == LEN_OUTPUT)
  254.       {
  255.       OutputBuffer[pos] = '\0';
  256.  
  257.       OutString(handle, OutputBuffer);
  258.  
  259.       pos = 0;
  260.       }
  261.    }
  262.  
  263. ///
  264.  
  265. /****************************************
  266.  * Standard Textausgabe, Zeichenkette   *
  267.  ****************************************
  268.  * I: Zeichenkette                      *
  269.  * O: ---                               *
  270.  ****************************************/
  271.  
  272. /// "OutString"
  273.  
  274. VOID OutString(BPTR handle, STRPTR string)
  275.    {
  276.    Write(handle, string, strlen(string));
  277.    if (Spying)
  278.       Write(KMS_LC->SpyHandle, string, strlen(string));
  279.    }
  280.  
  281. ///
  282.  
  283. /***************************************
  284.  * Einlesen der nächsten Kommandozeile *
  285.  ***************************************
  286.  * I: Prompt, Excludes, Default-Text,  *
  287.  * I: Länge, Flags                     *
  288.  * O: -9 : ShutDown                    *
  289.  * O: -1 : Eingabe-Timeout             *
  290.  * O: 0  : Leere Eingabe               *
  291.  * O: +n : Länge/Wert der Eingabe      *
  292.  ***************************************/
  293.  
  294. /// "CmdInput"
  295.  
  296. LONG CmdInput(STRPTR prompt, UWORD promptnum, STRPTR excludes, STRPTR deftxt, UWORD length, UWORD flags)
  297.    {
  298.    WORD c;
  299.    UWORD buffpos, crspos, result;
  300.    BOOL capsflag = FALSE, weiter = TRUE;
  301.  
  302.    KMS_LC->Session.Refresh = FALSE;
  303.  
  304.    struct HistoryNode *hpoint = KMS_LC->Session.HistPoint;
  305.    if (hpoint->Node.mln_Succ)
  306.       hpoint = hpoint->Node.mln_Succ;
  307.  
  308.    buffpos = 0;
  309.    crspos = 0;
  310.    result = 0;
  311.    *KMS_LC->Session.InputBuffer = '\0';
  312.  
  313.    if (length > LEN_CMDINPUT)
  314.       length = LEN_CMDINPUT;
  315.  
  316.    if (deftxt && strlen(deftxt) > length)
  317.       deftxt[length] = '\0';
  318.  
  319.    PPArg = deftxt;
  320.  
  321.    if (promptnum && (flags & INF_PROMPT))
  322.       SysMsg(promptnum);
  323.    else if (prompt)
  324.       ParsePrint(prompt, PF_NOLF|PF_NOBRK);
  325.  
  326.    PPArg = NULL;
  327.  
  328.    if (deftxt && (flags & INF_DEFBUF))
  329.       {
  330.       strcpy(KMS_LC->Session.InputBuffer, deftxt);
  331.       buffpos = strlen(KMS_LC->Session.InputBuffer);
  332.       crspos = buffpos;
  333.       Print(KMS_LC->Session.InputBuffer, PF_NOLF|PF_NOBRK);
  334.       }
  335.  
  336.    CursorOn();
  337.  
  338.    while(weiter)
  339.       {
  340.       c = InKey(-KMSBase->InputTimeout);
  341.  
  342.       if (c > 0) /* Gültiges Zeichen empfangen */
  343.          {
  344.          result = 0;
  345.  
  346.          if (!buffpos && (flags & INF_MSGMODE)
  347.                && (c >= '1' && c <= '9' && KMS_LC->Session.CurrentUser->UserData.Flags & UF_EMU_ANSI))
  348.             {
  349.             switch(c)
  350.                {
  351.                case '8': /* CRS UP */
  352.                   result = 22;
  353.                   break;
  354.                case '2': /* CRS DOWN */
  355.                   result = 23;
  356.                   break;
  357.                case '3': /* SHIFT CRS DOWN */
  358.                   result = 27;
  359.                   break;
  360.                case '1': /* SHIFT CRS UP */
  361.                   result = 26;
  362.                   break;
  363.                case '9': /* SHIFT CRS RIGHT */
  364.                   result = 29;
  365.                   break;
  366.                case '7': /* SHIFT CRS LEFT */
  367.                   result = 28;
  368.                   break;
  369.                case '6': /* CRS RIGHT */
  370.                   result = 24;
  371.                   break;
  372.                case '4': /* CRS LEFT */
  373.                   result = 25;
  374.                   break;
  375.                default:
  376.                   result = 0;
  377.                }
  378.             }
  379.  
  380.          if (result != 0 || c == 0x9b || c == 0x1b)
  381.             {
  382.             if ((result != 0 || (result = CheckCSI((TEXT)c))) && (KMS_LC->Session.CurrentUser->UserData.Flags & UF_EMU_ANSI))
  383.                {
  384.                /* CSI/ESC empfangen -> Prüfen auf Funktions-/Cursortaste */
  385.  
  386.                switch(result)
  387.                   {
  388.                   case 22: /* CRS UP */
  389.                      if (flags & INF_HISTORY)
  390.                         {
  391.                         UWORD n;
  392.                         CursorOff();
  393.                         for(n = crspos; n > 0; n--)
  394.                            OutChar(8);
  395.                         for(n = buffpos; n > 0; n--)
  396.                            OutChar(' ');
  397.                         for(n = buffpos; n > 0; n--)
  398.                            OutChar(8);
  399.                         OutChar(0);
  400.                         *KMS_LC->Session.InputBuffer = '\0';
  401.                         if (hpoint->Node.mln_Pred)
  402.                            {
  403.                            hpoint = hpoint->Node.mln_Pred;
  404.  
  405.                            if (hpoint->Node.mln_Pred)
  406.                               {
  407.                               strcpy(KMS_LC->Session.InputBuffer, hpoint->Cmd);
  408.                               Print(KMS_LC->Session.InputBuffer, PF_NOLF|PF_NOBRK);
  409.                               }
  410.                            }
  411.                         buffpos = strlen(KMS_LC->Session.InputBuffer);
  412.                         crspos = buffpos;
  413.                         CursorOn();
  414.                         }
  415.                      else if (flags & INF_CRSMODE)
  416.                         {
  417.                         strcpy(KMS_LC->Session.InputBuffer, "<CRS_UP>");
  418.  
  419.                         result = 1;
  420.                         buffpos = 0;
  421.                         crspos = 0;
  422.                         weiter = FALSE;
  423.                         }
  424.                      break;
  425.                   case 23: /* CRS DOWN */
  426.                      if (flags & INF_HISTORY)
  427.                         {
  428.                         UWORD n;
  429.                         CursorOff();
  430.                         for(n = crspos; n > 0; n--)
  431.                            OutChar(8);
  432.                         for(n = buffpos; n > 0; n--)
  433.                            OutChar(' ');
  434.                         for(n = buffpos; n > 0; n--)
  435.                            OutChar(8);
  436.                         OutChar(0);
  437.                         *KMS_LC->Session.InputBuffer = '\0';
  438.                         if (hpoint->Node.mln_Succ)
  439.                            {
  440.                            hpoint = hpoint->Node.mln_Succ;
  441.                            if (hpoint->Node.mln_Succ)
  442.                               {
  443.                               strcpy(KMS_LC->Session.InputBuffer, hpoint->Cmd);
  444.                               Print(KMS_LC->Session.InputBuffer, PF_NOLF|PF_NOBRK);
  445.                               }
  446.                            }
  447.                         buffpos = strlen(KMS_LC->Session.InputBuffer);
  448.                         crspos = buffpos;
  449.                         CursorOn();
  450.                         }
  451.                      else if (flags & INF_CRSMODE)
  452.                         {
  453.                         strcpy(KMS_LC->Session.InputBuffer, "<CRS_DN>");
  454.  
  455.                         result = 1;
  456.                         buffpos = 0;
  457.                         crspos = 0;
  458.                         weiter = FALSE;
  459.                         }
  460.                      break;
  461.                   case 24: /* CRS RIGHT */
  462.                      if (!buffpos && (flags & INF_MSGMODE))
  463.                         {
  464.                         Print(NULL, 0);
  465.  
  466.                         AutoAct = ACTION_CRS_RIGHT;
  467.  
  468.                         *KMS_LC->Session.InputBuffer = '\0';
  469.                         result = 0;
  470.                         weiter = FALSE;
  471.                         }
  472.                      else if (!buffpos && (flags & INF_CRSMODE))
  473.                         {
  474.                         strcpy(KMS_LC->Session.InputBuffer, "<CRS_RT>");
  475.  
  476.                         result = 1;
  477.                         buffpos = 0;
  478.                         crspos = 0;
  479.                         weiter = FALSE;
  480.                         }
  481.                      else if (crspos < buffpos)
  482.                         {
  483.                         OutChar(0x1b);
  484.                         OutChar('[');
  485.                         OutChar('C');
  486.                         OutChar(0);
  487.                         crspos++;
  488.                         }
  489.                      break;
  490.                   case 25: /* CRS LEFT */
  491.                      if (!buffpos && (flags & INF_MSGMODE))
  492.                         {
  493.                         Print(NULL, 0);
  494.                         
  495.                         AutoAct = ACTION_CRS_LEFT;
  496.  
  497.                         *KMS_LC->Session.InputBuffer = '\0';
  498.                         result = 0;
  499.                         weiter = FALSE;
  500.                         }
  501.                      else if (!buffpos && (flags & INF_CRSMODE))
  502.                         {
  503.                         strcpy(KMS_LC->Session.InputBuffer, "<CRS_LT>");
  504.  
  505.                         result = 1;
  506.                         buffpos = 0;
  507.                         crspos = 0;
  508.                         weiter = FALSE;
  509.                         }
  510.                      else if (crspos)
  511.                         {
  512.                         OutChar(0x1b);
  513.                         OutChar('[');
  514.                         OutChar('D');
  515.                         OutChar(0);
  516.                         crspos--;
  517.                         }
  518.                      break;
  519.                   case 26: /* SHIFT CRS UP */
  520.                      if (!buffpos && (flags & INF_MSGMODE))
  521.                         {
  522.                         Print(NULL, 0);
  523.                         
  524.                         AutoAct = ACTION_SHIFT_CRS_UP;
  525.  
  526.                         *KMS_LC->Session.InputBuffer = '\0';
  527.                         result = 0;
  528.                         weiter = FALSE;
  529.                         }
  530.                      else if (!buffpos && (flags & INF_CRSMODE))
  531.                         {
  532.                         strcpy(KMS_LC->Session.InputBuffer, "<SH_CRS_UP>");
  533.  
  534.                         result = 1;
  535.                         buffpos = 0;
  536.                         crspos = 0;
  537.                         weiter = FALSE;
  538.                         }
  539.                      break;
  540.                   case 27: /* SHIFT CRS DOWN */
  541.                      if (!buffpos && (flags & INF_MSGMODE))
  542.                         {
  543.                         Print(NULL, 0);
  544.                         
  545.                         AutoAct = ACTION_SHIFT_CRS_DOWN;
  546.  
  547.                         *KMS_LC->Session.InputBuffer = '\0';
  548.                         result = 0;
  549.                         weiter = FALSE;
  550.                         }
  551.                      else if (!buffpos && (flags & INF_CRSMODE))
  552.                         {
  553.                         strcpy(KMS_LC->Session.InputBuffer, "<SH_CRS_DN>");
  554.  
  555.                         result = 1;
  556.                         buffpos = 0;
  557.                         crspos = 0;
  558.                         weiter = FALSE;
  559.                         }
  560.                      break;
  561.                   case 28: /* SHIFT CRS LEFT */
  562.                      if (!buffpos && (flags & INF_MSGMODE))
  563.                         {
  564.                         Print(NULL, 0);
  565.                         
  566.                         AutoAct = ACTION_LIST_CURRENT;
  567.  
  568.                         *KMS_LC->Session.InputBuffer = '\0';
  569.                         result = 0;
  570.                         weiter = FALSE;
  571.                         }
  572.                      else if (!buffpos && (flags & INF_CRSMODE))
  573.                         {
  574.                         strcpy(KMS_LC->Session.InputBuffer, "<SH_CRS_LT>");
  575.  
  576.                         result = 1;
  577.                         buffpos = 0;
  578.                         crspos = 0;
  579.                         weiter = FALSE;
  580.                         }
  581.                      else while(crspos)
  582.                         {
  583.                         OutChar(0x1b);
  584.                         OutChar('[');
  585.                         OutChar('D');
  586.                         OutChar(0);
  587.                         crspos--;
  588.                         }
  589.                      break;
  590.                   case 29: /* SHIFT CRS RIGHT */
  591.                      if (!buffpos && (flags & INF_MSGMODE))
  592.                         {
  593.                         Print(NULL, 0);
  594.                         
  595.                         AutoAct = ACTION_SHIFT_CRS_RIGHT;
  596.  
  597.                         *KMS_LC->Session.InputBuffer = '\0';
  598.                         result = 0;
  599.                         weiter = FALSE;
  600.                         }
  601.                      else if (!buffpos && (flags & INF_CRSMODE))
  602.                         {
  603.                         strcpy(KMS_LC->Session.InputBuffer, "<SH_CRS_RT>");
  604.  
  605.                         result = 1;
  606.                         buffpos = 0;
  607.                         crspos = 0;
  608.                         weiter = FALSE;
  609.                         }
  610.                      else while(crspos < buffpos)
  611.                         {
  612.                         OutChar(0x1b);
  613.                         OutChar('[');
  614.                         OutChar('C');
  615.                         OutChar(0);
  616.                         crspos++;
  617.                         }
  618.                      break;
  619.                   default:
  620.                      DoFKey(result);
  621.                      break;
  622.                   }
  623.                }
  624.             else if (c == 0x1b && (flags & INF_CRSMODE))
  625.                {
  626.                strcpy(KMS_LC->Session.InputBuffer, "<ESC>");
  627.                result = 1;
  628.                buffpos = 0;
  629.                crspos = 0;
  630.                weiter = FALSE;
  631.                }
  632.             }
  633.          else if (c == 8)
  634.             {
  635.             if (crspos)
  636.                {
  637.                /* BACKSPACE */
  638.  
  639.                buffpos--;
  640.                crspos--;
  641.  
  642.                if ((KMS_LC->Session.CurrentUser->UserData.Flags & UF_EMU_ANSI) && !(flags & INF_NOINSERT))
  643.                   {
  644.                   OutChar(c);
  645.                   OutChar(0x1b);
  646.                   OutChar('[');
  647.                   OutChar('P');
  648.                   OutChar(0);
  649.                   }
  650.                else
  651.                   {
  652.                   OutChar(c);
  653.                   OutChar(' ');
  654.                   OutChar(c);
  655.                   OutChar(0);
  656.                   }
  657.  
  658.                DelInputChar(crspos);
  659.                }
  660.             }
  661.          else if (c == 127)
  662.             {
  663.             if (crspos < buffpos && (KMS_LC->Session.CurrentUser->UserData.Flags & UF_EMU_ANSI) && !(flags & INF_NOINSERT))
  664.                {
  665.                /* DELETE */
  666.  
  667.                buffpos--;
  668.  
  669.                OutChar(0x1b);
  670.                OutChar('[');
  671.                OutChar('P');
  672.                OutChar(0);
  673.  
  674.                DelInputChar(crspos);
  675.                }
  676.             }
  677.          else if (c == 1)
  678.             {
  679.             /* Toggle Insert <-> Overstrike */
  680.  
  681.             KMS_LC->Session.CurrentUser->UserData.Flags ^= UF_EDIT_INSERT;
  682.             }
  683.          else if (c == 24)
  684.             {
  685.             /* Ctrl-X: Input löschen */
  686.  
  687.             UWORD n;
  688.             CursorOff();
  689.             for(n = crspos; n > 0; n--)
  690.                OutChar(8);
  691.             for(n = buffpos; n > 0; n--)
  692.                OutChar(' ');
  693.             for(n = buffpos; n > 0; n--)
  694.                OutChar(8);
  695.             OutChar(0);
  696.             *KMS_LC->Session.InputBuffer = '\0';
  697.             buffpos = 0;
  698.             crspos = 0;
  699.             CursorOn();
  700.             }
  701.          else if ((c == 32 || c == '\r' || c == '5') && !buffpos && (flags & INF_MSGMODE))
  702.             {
  703.             Print(NULL, 0);
  704.  
  705.             AutoAct = ACTION_CRS_RIGHT;
  706.              
  707.             *KMS_LC->Session.InputBuffer = '\0';
  708.             result = 0;
  709.             weiter = FALSE;
  710.             }
  711.          else if (c > 31
  712.                  && (buffpos < length || (crspos < buffpos && ((flags & INF_NOINSERT) || !(KMS_LC->Session.CurrentUser->UserData.Flags & UF_EDIT_INSERT))))
  713.                  && (!(flags & INF_NUMERIC) || (c >= 48 && c <= 57)))
  714.             {
  715.             /* Zeichen ausgeben und merken im KMS_LC->Session.InputBuffer */
  716.  
  717.             if (flags & INF_SPECIAL)
  718.                {
  719.                if (!buffpos || c == 32 || c == '-')
  720.                   capsflag = FALSE;
  721.                }
  722.  
  723.             if ((flags & INF_UPCASE) || ((flags & INF_SPECIAL) && !capsflag))
  724.                {
  725.                c = toupper(c);
  726.  
  727.                if ((flags & INF_SPECIAL) && c != 32 && c != '-')
  728.                   capsflag = TRUE;
  729.                }
  730.  
  731.             if (!excludes || (!strchr(excludes, c) && (flags & INF_EXCLUDE))
  732.                          || (strchr(excludes, c) && !(flags & INF_EXCLUDE)))
  733.                {
  734.                if (crspos < buffpos && !(flags & INF_NOINSERT) && (KMS_LC->Session.CurrentUser->UserData.Flags & UF_EDIT_INSERT))
  735.                   {
  736.                   OutChar(0x1b);
  737.                   OutChar('[');
  738.                   OutChar('@');
  739.  
  740.                   InsInputChar(crspos);
  741.                   }
  742.  
  743.                if (flags & INF_HIDE)
  744.                   OutChar('*'); 
  745.                else
  746.                   OutChar(c);
  747.  
  748.                OutChar(0);
  749.  
  750.                KMS_LC->Session.InputBuffer[crspos++] = c;
  751.  
  752.                if (crspos > buffpos || (!(flags & INF_NOINSERT) && (KMS_LC->Session.CurrentUser->UserData.Flags & UF_EDIT_INSERT)))
  753.                   {
  754.                   buffpos++;
  755.                   KMS_LC->Session.InputBuffer[buffpos] = '\0';
  756.                   }
  757.                }
  758.             }
  759.  
  760.          if (weiter)
  761.             {
  762.             if ((c == '\r' && (!(flags & INF_NOEMPTY) || buffpos))
  763.                 || ((flags & INF_FORCECR) && buffpos == length))
  764.                {
  765.                if (!(flags & INF_NOLF))
  766.                   Print(NULL, 0);
  767.                KMS_LC->Session.InputBuffer[buffpos] = '\0';
  768.                if (flags & INF_NUMERIC)
  769.                   result = atoi(KMS_LC->Session.InputBuffer);
  770.                else
  771.                   result = strlen(KMS_LC->Session.InputBuffer);
  772.                weiter = FALSE;
  773.                }
  774.             }
  775.          }
  776.       else if (c == 0)
  777.          {
  778.          /* Nix gekommen oder ARexx-Msg wurde gerade abgearbeitet:
  779.             Evt. Eingabezeile refreshen */
  780.  
  781.          if (KMS_LC->Session.Refresh)
  782.             {
  783.             CursorOff();
  784.             OutChar('\r');
  785.             PPArg = deftxt;
  786.             if (promptnum && (flags & INF_PROMPT))
  787.                SysMsg(promptnum);
  788.             else if (prompt)
  789.                ParsePrint(prompt, PF_NOLF|PF_NOBRK);
  790.             PPArg = NULL;
  791.             Print(KMS_LC->Session.InputBuffer, PF_NOLF|PF_NOBRK);
  792.             CursorOn();
  793.  
  794.             KMS_LC->Session.Refresh = FALSE;
  795.             }
  796.          }
  797.       else if (c == -9)
  798.          {
  799.          /* ShutDown / Lock / Rexx-Logout */
  800.  
  801.          Print(NULL, 0);
  802.          *KMS_LC->Session.InputBuffer = '\0';
  803.          CursorOff();
  804.  
  805.          return -9;
  806.          }
  807.       else
  808.          {
  809.          /* Timeout aufgetreten */
  810.  
  811.          CursorOff();
  812.          Print(NULL, 0);
  813.  
  814.          LazyCount++;
  815.          if (!PlopCheck(LazyCount, flags))
  816.             return -1;
  817.  
  818.          /* Wenn nicht Plop, erneute Eingabe */
  819.  
  820.          PPArg = deftxt;
  821.          if (promptnum && (flags & INF_PROMPT))
  822.             SysMsg(promptnum);
  823.          else if (prompt)
  824.             ParsePrint(prompt, PF_NOLF|PF_NOBRK);
  825.          PPArg = NULL;
  826.          Print(KMS_LC->Session.InputBuffer, PF_NOLF|PF_NOBRK);
  827.          CursorOn();
  828.          }
  829.       }
  830.  
  831.    CursorOff();
  832.  
  833.    if (flags & INF_HISTORY)
  834.       {
  835.       buffpos--;
  836.       while(buffpos && KMS_LC->Session.InputBuffer[buffpos] == ' ')
  837.          KMS_LC->Session.InputBuffer[buffpos--] = '\0';
  838.       if (KMS_LC->Session.InputBuffer[buffpos] == ' ')
  839.          KMS_LC->Session.InputBuffer[buffpos] = '\0';
  840.       result = strlen(KMS_LC->Session.InputBuffer);
  841.  
  842.       /* History-Eintrag */
  843.  
  844.       if (*KMS_LC->Session.InputBuffer && (!KMS_LC->HistCount || stricmp(KMS_LC->Session.HistPoint->Cmd, KMS_LC->Session.InputBuffer)))
  845.          {
  846.          if (KMS_LC->HistCount < KMSBase->MaxHistCount)
  847.             {
  848.             if (hpoint = (struct HistoryNode *)AllocMem((ULONG)sizeof(struct HistoryNode), MEMF_PUBLIC|MEMF_CLEAR))
  849.                {
  850.                AddTail((struct List *)&KMS_LC->HistoryList, (struct Node *)hpoint);
  851.                KMS_LC->HistCount++;
  852.                }
  853.             }
  854.          else
  855.             {
  856.             hpoint = KMS_LC->HistoryList.mlh_Head;
  857.             RemHead((struct Node *)&KMS_LC->HistoryList);
  858.             AddTail((struct List *)&KMS_LC->HistoryList, (struct Node *)hpoint);
  859.             }
  860.  
  861.          if (hpoint)
  862.             {
  863.             strcpy(hpoint->Cmd, KMS_LC->Session.InputBuffer);
  864.             KMS_LC->Session.HistPoint = hpoint;
  865.             }
  866.          }
  867.       }
  868.  
  869.    if (deftxt && !(flags & INF_DEFBUF) && *KMS_LC->Session.InputBuffer == '\0')
  870.       {
  871.       strcpy(KMS_LC->Session.InputBuffer, deftxt);
  872.       if (flags & INF_NUMERIC)
  873.          result = atoi(KMS_LC->Session.InputBuffer);
  874.       else
  875.          result = strlen(KMS_LC->Session.InputBuffer);
  876.       }
  877.  
  878.    return result;
  879.    }
  880.  
  881. ///
  882.  
  883. /*************************************
  884.  * Timeout-Überprüfung               *
  885.  *************************************
  886.  * I: >0, wenn Timout, Input-Flags   *
  887.  * O: FALSE: ShutDown/Timeout        *
  888.  * O: TRUE : Weitermachen            *
  889.  *************************************/
  890.  
  891. /// "PlopCheck"
  892.  
  893. BOOL PlopCheck(UBYTE count, UWORD flags)
  894.    {
  895.    WORD timeleft;
  896.  
  897.    static WORD merk = 0;
  898.  
  899.    if (ShutDown == SHUTDOWN_IMMEDIATE || Plop)
  900.       return FALSE;
  901.  
  902.    /* Timeout bei Input? */
  903.  
  904.    if (count)
  905.       {
  906.       SysMsg(SYSEVENT);
  907.  
  908.       if (count > KMSBase->InputTimeoutWarnings)
  909.          {
  910.          SysMsg(BIBI_SLEEPY);
  911.  
  912.          Plop = PLOP_INTIMEOUT;
  913.  
  914.          return FALSE;
  915.          }
  916.       else
  917.          SysMsg(WAKE_UP_PLEASE);
  918.       }
  919.    else
  920.       {
  921.       /* Prüfen der Verbindungszeit */
  922.  
  923.       if (!KMS_LC->Session.MaxConnectTime) /* Ewig Zeit :-) */
  924.          return TRUE;
  925.  
  926.       timeleft = KMS_LC->Session.MaxConnectTime - (MakeTime(NULL, KMS_LC->Session.LoginTime, 0) / 60);
  927.  
  928.       if (timeleft <= 0)
  929.          {
  930.          SysMsg(SYSEVENT);
  931.          SysMsg(SYSTIME_EXCEEDED);
  932.          merk = 0;
  933.  
  934.          Plop = PLOP_SYSTIMEOUT;
  935.  
  936.          return FALSE;
  937.          }
  938.       else if (timeleft <= KMSBase->MaxConnectWarnings)
  939.          {
  940.          if (timeleft > 1 && timeleft != merk)
  941.             {
  942.             SysMsg(SYSEVENT);
  943.             SysMsg(X_MINUTES_LEFT);
  944.             }
  945.          else if (timeleft != merk)
  946.             {
  947.             SysMsg(SYSEVENT);
  948.             SysMsg(ONE_MINUTE_LEFT);
  949.             }
  950.  
  951.          merk = timeleft;
  952.          }
  953.       }
  954.  
  955.    return TRUE;
  956.    }
  957.  
  958. ///
  959.  
  960. /***********************************
  961.  * Warten auf ein Zeichen (Unused) *
  962.  ***********************************
  963.  * I: Timout-Zeit in Sekunden      *
  964.  * O: Zeichen bzw. -1 für Timeout  *
  965.  * O:              -9 für ShutDown *
  966.  ***********************************/
  967.  
  968. /// "InKeyNew"
  969.  
  970. WORD InKeyNew(WORD timeout)
  971.    {
  972.    TEXT c = 0;
  973.    ULONG insignal;
  974.    static BOOL timeractive = FALSE;
  975.  
  976.    /* Im Lokalbetrieb soll es keine Timeouts geben */
  977.  
  978.    if (KMS_LC->Device & DEV_CONSOLE)
  979.       timeout = 0;
  980.  
  981.    /* Soll evt. weitergewartet werden? */
  982.  
  983.    if (timeout < 0)
  984.       {
  985.       if (!timeractive)
  986.          timeout = -timeout;
  987.       else
  988.          timeout = 0;
  989.       }
  990.  
  991.    /* Falls nötig, Input-Timer starten */
  992.  
  993.    if (timeout)
  994.       {
  995.       InputPacket->dp_Arg1 = timeout * 1000000L;
  996.  
  997.       SendPkt(InputPacket,
  998.               ((struct FileHandle *)BADDR(KMS_LC->InHandle))->fh_Type,
  999.               InputPacket->dp_Link->mn_ReplyPort);
  1000.  
  1001.       timeractive = TRUE;
  1002.       }
  1003.  
  1004.    while(1)
  1005.       {
  1006.       insignal = Wait(RexxSignal | InputSignal);
  1007.  
  1008.       if ((insignal & InputSignal) == InputSignal)
  1009.          {
  1010.          GetMsg(InputPacket->dp_Link->mn_ReplyPort);
  1011.  
  1012.          timeractive = FALSE;
  1013.  
  1014.          if (InputPacket->dp_Res1 == DOSFALSE)
  1015.             {
  1016.             /* Nix gekommen, Break prüfen */
  1017.  
  1018.             if (CheckSignal(SIGBREAKF_CTRL_C))
  1019.                {
  1020.                /* Plop */
  1021.  
  1022.                Plop = PLOP_BREAKC;
  1023.                return -9;
  1024.                }
  1025.  
  1026.             /* Timeout */
  1027.  
  1028.             return -1;
  1029.             }
  1030.          else
  1031.             {
  1032.             /* Zeichen abholen */
  1033.  
  1034.             if (Read(KMS_LC->InHandle, &c, 1) == 1)
  1035.                {
  1036.                c = KMSBase->CharIn[KMS_LC->Session.CurrentUser->UserData.CharSet][c];
  1037.                if (c == 3)
  1038.                   SetSignal(0, SIGBREAKF_CTRL_C);
  1039.                
  1040.                return (WORD)c;
  1041.                }
  1042.             else
  1043.                {
  1044.                /* Plop */
  1045.  
  1046.                Plop = PLOP_BREAKC;
  1047.                return -9;
  1048.                }
  1049.             }
  1050.          }
  1051.  
  1052.       if ((insignal & RexxSignal) == RexxSignal)
  1053.          {
  1054.          dispRexxPort();
  1055.  
  1056.          /* Hier muesste ACTION_WAIT_CHAR abgebrochen werden!
  1057.             Geht aber nicht! */
  1058.  
  1059.          if (KMS_LC->Session.Refresh)
  1060.             return 0;
  1061.  
  1062.          if (ShutDown == SHUTDOWN_IMMEDIATE || KMS_LC->Locked == LOCK_IMMEDIATE || Plop)
  1063.             return -9;
  1064.          }
  1065.       }
  1066.    }
  1067.  
  1068. ///
  1069.  
  1070. /***********************************
  1071.  * Warten auf ein Zeichen          *
  1072.  ***********************************
  1073.  * I: Timout-Zeit in Sekunden      *
  1074.  * O: Zeichen bzw. -1 für Timeout  *
  1075.  * O:              -9 für ShutDown *
  1076.  ***********************************/
  1077.  
  1078. /// "InKey"
  1079.  
  1080. WORD InKey(WORD timeset)
  1081.    {
  1082.    static UWORD timeout = 0;
  1083.    TEXT c = 0;
  1084.    BOOL endless;
  1085.  
  1086.    if (timeset >= 0)
  1087.       timeout = timeset;
  1088.    else if (timeout == 0)
  1089.       timeout = -timeset;
  1090.  
  1091.    /* Im Lokalbetrieb soll es keine Timeouts geben */
  1092.  
  1093.    if (KMS_LC->Device & DEV_CONSOLE)
  1094.       endless = TRUE;
  1095.    else
  1096.       endless = FALSE;
  1097.  
  1098.    while(endless || timeout)
  1099.       {
  1100.       /* 1s auf Zeichen warten */
  1101.  
  1102.       if (WaitForChar(KMS_LC->InHandle, 1000000L) == DOSFALSE)
  1103.          {
  1104.          /* Nix gekommen, Break prüfen und Rexx-Port abfragen */
  1105.  
  1106.          if (CheckSignal(SIGBREAKF_CTRL_C))
  1107.             Plop = PLOP_BREAKC;
  1108.          else
  1109.             {
  1110.             dispRexxPort();
  1111.             if (KMS_LC->Session.Refresh && timeset < 0)
  1112.                return 0;
  1113.             }
  1114.  
  1115.          if (ShutDown == SHUTDOWN_IMMEDIATE || KMS_LC->Locked == LOCK_IMMEDIATE || Plop)
  1116.             return -9;
  1117.          }
  1118.       else
  1119.          {
  1120.          /* Zeichen abholen */
  1121.  
  1122.          if (Read(KMS_LC->InHandle, &c, 1) == 1)
  1123.             {
  1124.             c = KMSBase->CharIn[KMS_LC->Session.CurrentUser->UserData.CharSet][c];
  1125.             if (c == 3)
  1126.                SetSignal(0, SIGBREAKF_CTRL_C);
  1127.  
  1128.             timeout = 0;
  1129.             
  1130.             return (WORD)c;
  1131.             }
  1132.          else
  1133.             {
  1134.             Plop = PLOP_BREAKC;
  1135.  
  1136.             return -9;
  1137.             }
  1138.          }
  1139.  
  1140.       timeout--;
  1141.       }
  1142.  
  1143.    /* Eingabetimeout */
  1144.  
  1145.    return -1;
  1146.    }
  1147.  
  1148. ///
  1149.  
  1150. /**********************************
  1151.  * Tastatur/Serialcheck           *
  1152.  **********************************
  1153.  * I: ---                         *
  1154.  * O: Zeichen bzw. 0              *
  1155.  **********************************/
  1156.  
  1157. /// "ReadKey"
  1158.  
  1159. TEXT ReadKey(VOID)
  1160.    {
  1161.    TEXT c = 0;
  1162.  
  1163.    if (WaitForChar(KMS_LC->InHandle, 0) == DOSFALSE)
  1164.       {
  1165.       if (CheckSignal(SIGBREAKF_CTRL_C))
  1166.          Plop = PLOP_BREAKC;
  1167.  
  1168.       return 0;
  1169.       }
  1170.  
  1171.    if (Read(KMS_LC->InHandle, &c, 1) == 1)
  1172.       {
  1173.       c = KMSBase->CharIn[KMS_LC->Session.CurrentUser->UserData.CharSet][c];
  1174.       if (c == 3)
  1175.          SetSignal(0, SIGBREAKF_CTRL_C);
  1176.  
  1177.       return c;
  1178.       }
  1179.    else
  1180.       {
  1181.       Plop = PLOP_BREAKC;
  1182.  
  1183.       return 0;
  1184.       }
  1185.    }
  1186.  
  1187. ///
  1188.  
  1189. /*********************************************
  1190.  * Prüfen auf Funktionstaste/Helptaste       *
  1191.  *********************************************
  1192.  * I: ---                                    *
  1193.  * O: 1-20: F-Taste, 21: HELP, 22-26: Cursor *
  1194.  *********************************************/
  1195.  
  1196. /// "CheckCSI"
  1197.  
  1198. UWORD CheckCSI(TEXT intro)
  1199.    {
  1200.    UWORD result;
  1201.    TEXT c;
  1202.    TEXT buff[10];
  1203.    UWORD pos = 0;
  1204.    BOOL ok = FALSE;
  1205.  
  1206.    *buff = '\0';
  1207.    if (intro != 0x1b)
  1208.       ok = TRUE;
  1209.  
  1210.    while(WaitForChar(KMS_LC->InHandle, 500000L)) /* max. 0,5 sec warten */
  1211.       {
  1212.       if (Read(KMS_LC->InHandle, &c, 1) != 1)
  1213.          {
  1214.          Plop = PLOP_BREAKC;
  1215.          return 0;
  1216.          }
  1217.  
  1218.       if (!ok)
  1219.          {
  1220.          if (c == '[')
  1221.             ok = TRUE;
  1222.          else
  1223.             return 0;
  1224.          }
  1225.       else
  1226.          {
  1227.          buff[pos++] = c;
  1228.          buff[pos] = '\0';
  1229.          }
  1230.  
  1231.       /* Wurde Sondertaste gedrückt? */
  1232.  
  1233.       if (!strcmp(buff, "?~"))
  1234.          {
  1235.          /* HELP-Taste */
  1236.  
  1237.          return 21;
  1238.          }
  1239.       else if (*buff >= 'A' && *buff <= 'D')
  1240.          {
  1241.          /* Cursor-Taste */
  1242.  
  1243.          return *buff-65+22;
  1244.          }
  1245.       else if (*buff == 'T')
  1246.          {
  1247.          /* SHIFT CURSOR UP */
  1248.  
  1249.          return 26;
  1250.          }
  1251.       else if (*buff == 'S')
  1252.          {
  1253.          /* SHIFT CURSOR DOWN */
  1254.  
  1255.          return 27;
  1256.          }
  1257.       else if (!strcmp(buff, " A"))
  1258.          {
  1259.          /* SHIFT CURSOR LEFT */
  1260.  
  1261.          return 28;
  1262.          }
  1263.       else if (!strcmp(buff, " @"))
  1264.          {
  1265.          /* SHIFT CURSOR RIGHT */
  1266.  
  1267.          return 29;
  1268.          }
  1269.       else if (pos > 0 && buff[pos-1] == '~')
  1270.          {
  1271.          /* Funktionstaste */
  1272.  
  1273.          result = atoi(buff);
  1274.          if (result >= 0 && result <= 19)
  1275.             return result + 1;
  1276.          else
  1277.             return 0;
  1278.          }
  1279.  
  1280.       if (pos == 9)
  1281.          return 0;
  1282.       }
  1283.  
  1284.    return 0;
  1285.    }
  1286.  
  1287. ///
  1288.  
  1289. /*********************************************
  1290.  * Suchen einer Zeichenfolge in einem String *
  1291.  *********************************************
  1292.  * I: Suchstring, durchsuchter String        *
  1293.  * O: TRUE/FALSE : gefunden/nicht gefunden   *
  1294.  *********************************************/
  1295.  
  1296. /// "StringSearch"
  1297.  
  1298. BOOL StringSearch(STRPTR string1, STRPTR string2)
  1299.    {
  1300.    UWORD stelle, len1, len2;
  1301.  
  1302.    len1 = strlen(string1);
  1303.    len2 = strlen(string2);
  1304.    for(stelle = 0; stelle < len1; stelle++)
  1305.       {
  1306.       if (strncmp(string1+stelle, string2, len2) == 0)
  1307.          return TRUE; /* Gefunden! */
  1308.       }
  1309.    return FALSE;
  1310.    }
  1311.  
  1312. ///
  1313.  
  1314. /******************************************
  1315.  * Funktionstasten auswerten              *
  1316.  ******************************************
  1317.  * I: Tastencode                          *
  1318.  * O: ---                                 *
  1319.  ******************************************/
  1320.  
  1321. /// "DoFKey"
  1322.  
  1323. VOID DoFKey(UWORD code)
  1324.    {
  1325.    switch(code)
  1326.       {
  1327.       default:
  1328.          break;
  1329.       }
  1330.    }
  1331.  
  1332. ///
  1333.  
  1334. /******************************************
  1335.  * Datum / Zeit aufbereiten               *
  1336.  ******************************************
  1337.  * I: Ergebnis-String, Offset, Festzeit   *
  1338.  * O: Sekunden online                     *
  1339.  ******************************************/
  1340.  
  1341. /// "MakeTime"
  1342.  
  1343. ULONG MakeTime(STRPTR buff, time_t difftime, time_t fixtime)
  1344.    {
  1345.    time_t just;
  1346.    struct tm *zt;
  1347.  
  1348.    /* Wenn fixtime > 0, dann diesen Wert als Zeit nehmen, sonst akt. Zeit */
  1349.  
  1350.    if (fixtime)
  1351.       just = fixtime;
  1352.    else
  1353.       just = time(NULL);
  1354.  
  1355.    /* Wenn difftime > 0, dann Differenz berechnen */
  1356.  
  1357.    if (difftime)
  1358.       just -= difftime;
  1359.  
  1360.    if (buff)
  1361.       {
  1362.       if (difftime)
  1363.          {
  1364.          UBYTE h = just / 3600;
  1365.          UBYTE m = (just - h * 3600) / 60;
  1366.          UBYTE s = just % 60;
  1367.  
  1368.          sprintf(buff, "--.--.-- %02d:%02d:%02d", h, m, s);
  1369.          }
  1370.       else
  1371.          {
  1372.          zt = localtime(&just);
  1373.          sprintf(buff, "%02d.%02d.%02d %02d:%02d:%02d", zt->tm_mday, zt->tm_mon+1, zt->tm_year, zt->tm_hour, zt->tm_min, zt->tm_sec);
  1374.          }
  1375.       }
  1376.  
  1377.    return (ULONG)just;
  1378.    }
  1379.  
  1380. ///
  1381.  
  1382. /**********************
  1383.  * Cursor einschalten *
  1384.  **********************
  1385.  * I: ---             *
  1386.  * O: ---             *
  1387.  **********************/
  1388.  
  1389. /// "CursorOn"
  1390.  
  1391. VOID CursorOn(VOID)
  1392.    {
  1393.    if (!KMS_LC->Cursor && (KMS_LC->Device & DEV_CONSOLE))
  1394.       {
  1395.       Print("\33[ p", PF_NOLF|PF_NOBRK);
  1396.       KMS_LC->Cursor = TRUE;
  1397.       }
  1398.    }
  1399.  
  1400. ///
  1401.  
  1402. /**********************
  1403.  * Cursor ausschalten *
  1404.  **********************
  1405.  * I: ---             *
  1406.  * O: ---             *
  1407.  **********************/
  1408.  
  1409. /// "CursorOff"
  1410.  
  1411. VOID CursorOff(VOID)
  1412.    {
  1413.    if (KMS_LC->Cursor && (KMS_LC->Device & DEV_CONSOLE))
  1414.       {
  1415.       Print("\33[0 p", PF_NOLF|PF_NOBRK);
  1416.       KMS_LC->Cursor = FALSE;
  1417.       }
  1418.    }
  1419.  
  1420. ///
  1421.  
  1422. /******************************************
  1423.  * Ein Zeichen aus                        *
  1424.  * KMS_LC->Session.InputBuffer entfernen, *
  1425.  * Rest entsprechend nachziehen           *
  1426.  ******************************************
  1427.  * I: Zeichenposition                     *
  1428.  * O: ---                                 *
  1429.  ******************************************/
  1430.  
  1431. /// "DelInputChar"
  1432.  
  1433. VOID DelInputChar(UWORD pos)
  1434.    {
  1435.    while(KMS_LC->Session.InputBuffer[pos])
  1436.       KMS_LC->Session.InputBuffer[pos] = KMS_LC->Session.InputBuffer[++pos];
  1437.    }
  1438.  
  1439. ///
  1440.  
  1441. /******************************************
  1442.  * Ein Zeichen in                         *
  1443.  * KMS_LC->Session.InputBuffer einfuegen  *
  1444.  * Rest entsprechend vorschieben          *
  1445.  ******************************************
  1446.  * I: Zeichenposition                     *
  1447.  * O: ---                                 *
  1448.  ******************************************/
  1449.  
  1450. /// "InsInputChar"
  1451.  
  1452. VOID InsInputChar(UWORD pos)
  1453.    {
  1454.    UWORD b = strlen(KMS_LC->Session.InputBuffer) + 1;
  1455.  
  1456.    KMS_LC->Session.InputBuffer[b--] = '\0';
  1457.  
  1458.    while(b != pos)
  1459.       KMS_LC->Session.InputBuffer[b] = KMS_LC->Session.InputBuffer[--b];
  1460.    }
  1461.  
  1462. ///
  1463.  
  1464. /******************************************
  1465.  * Chat Ausgabe                           *
  1466.  ******************************************
  1467.  * I: Zeichenkette, Flags                 *
  1468.  * O: ---                                 *
  1469.  ******************************************/
  1470.  
  1471. /// "ChatOut"
  1472.  
  1473. VOID ChatOut(STRPTR text, UWORD flags)
  1474.    {
  1475.    TEXT target[LEN_NUMBER+4+1];
  1476.    TEXT command[LEN_REXXBUFF+1];
  1477.    struct KMSNode *member = KMSBase->MemberList.mlh_Head;
  1478.  
  1479.    if (flags & CO_NOPROMPT)
  1480.       sprintf(command, "OUT CHAT TEXT %s\r\n", text);
  1481.    else if (flags & CO_EMOTE)
  1482.       sprintf(command, "OUT CHAT TEXT %s %s\r\n", KMS_LC->Session.CurrentUser->UserData.Name, text);
  1483.    else
  1484.       sprintf(command, "OUT CHAT TEXT %s: %s\r\n", KMS_LC->Session.CurrentUser->UserData.Name, text);
  1485.  
  1486.    TakeMSem(FALSE);
  1487.  
  1488.    while(member->Node.mln_Succ)
  1489.       {
  1490.       if ((member->LCPtr->ID != KMS_LC->ID || (flags & CO_METOO)) && member->LCPtr->Session.CommMode == CM_CHAT)
  1491.          {
  1492.          if (!stricmp(KMS_LC->Session.ChatChannel, member->LCPtr->Session.ChatChannel))
  1493.             {
  1494.             sprintf(target, "KMS.%d", member->LCPtr->ID);
  1495.             sendRexxCmd(command, NULL, NULL, NULL, NULL, target);
  1496.             }
  1497.          }
  1498.  
  1499.       member = member->Node.mln_Succ;
  1500.       }
  1501.  
  1502.    DropMSem();
  1503.    }
  1504.  
  1505. ///
  1506.  
  1507. /*************************
  1508.  * Standardfehlerausgabe *
  1509.  *************************
  1510.  *** I: Text             *
  1511.  *** O: ---              *
  1512.  *************************/
  1513.  
  1514. /// "Error"
  1515.  
  1516. VOID Error(STRPTR str)
  1517.    {
  1518.    if (StdErr && str)
  1519.       {
  1520.       Write(StdErr, str, strlen(str));
  1521.       Write(StdErr, "\n", 1);
  1522.       }
  1523.    }
  1524.  
  1525. ///
  1526.  
  1527.